package com.sxjh.controller.ny;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sxjh.common.BaseController;
import com.sxjh.common.Constant;
import com.sxjh.common.Result;
import com.sxjh.common.ZPage;
import com.sxjh.entity.param.ReportsDetailParam;
import com.sxjh.entity.param.ReportsListParam;
import com.sxjh.service.PdfService;
import com.sxjh.service.TaskService;
import com.sxjh.uitl.ExcelUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 内部倒运报表
 * </p>
 *
 * @author guanxy
 * @since 2023-06-15
 */
@Api(tags = "内部倒运报表")
@RestController
@RequestMapping("/reports")
public class ReportsController extends BaseController {

    @Autowired
    private TaskService taskService;

    @Autowired
    private ExcelUtils excelUtils;

    @Autowired
    private PdfService pdfService;

    @Autowired
    private HttpServletResponse response;

    @ApiOperation("磅单日报表")
    @PostMapping(value = "/day")
    public Result<ZPage<ReportsListParam>> day(@RequestBody ReportsListParam param) {
        IPage iPage = new Page(param.getCurrent(), param.getSize());
        if (param.getSize() == -1) {
            iPage.setSize(Constant.maxSize);
        }
        IPage<ReportsListParam> aPage = taskService.reportList(iPage, param);
        ZPage<ReportsListParam> zPage = copyPage(aPage, ReportsListParam::new);

        List<ReportsListParam> records = zPage.getRecords();
        zPage.setRecords(daySort(records, param.getSortType(), param.getOrderType()));
        return Result.ok(zPage);
    }

    /**
     * 日报表排序
     * @param records
     * @param orderType
     * @param sortType
     */
    private List<ReportsListParam> daySort(List<ReportsListParam> records, Integer sortType, Integer orderType) {
        if (orderType != null && sortType != null) {
            if (1 == sortType) {// 物料名称
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getMaterialName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getMaterialName).reversed()).collect(Collectors.toList());
                }
            } else if (2 == sortType) {// 车数
                if (1 == orderType) {
                    records.sort((a,b)->a.getVehNumberCount().compareTo(b.getVehNumberCount()));
                } else {
                    records.sort((b,a)->a.getVehNumberCount().compareTo(b.getVehNumberCount()));
                }
            } else if (3 == sortType) {// 毛重
                if (1 == orderType) {
                    records.sort((a,b)->a.getGrossCount().compareTo(b.getGrossCount()));
                } else {
                    records.sort((b,a)->a.getGrossCount().compareTo(b.getGrossCount()));
                }
            } else if (4 == sortType) {// 皮重
                if (1 == orderType) {
                    records.sort((a,b)->a.getTareCount().compareTo(b.getTareCount()));
                } else {
                    records.sort((b,a)->a.getTareCount().compareTo(b.getTareCount()));
                }
            } else if (5 == sortType) {// 净重
                if (1 == orderType) {
                    records.sort((a,b)->a.getNetCount().compareTo(b.getNetCount()));
                } else {
                    records.sort((b,a)->a.getNetCount().compareTo(b.getNetCount()));
                }
            } else if (6 == sortType) {// 装车点
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationUpName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationUpName).reversed()).collect(Collectors.toList());
                }
            } else if (7 == sortType) {// 卸车点
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationDownName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationDownName).reversed()).collect(Collectors.toList());
                }
            } else if (8 == sortType) {// 装车点所属工厂
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationUpFactoryName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationUpFactoryName).reversed()).collect(Collectors.toList());
                }
            } else if (9 == sortType) {// 装车点所属车间
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationUpWorkshopName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationUpWorkshopName).reversed()).collect(Collectors.toList());
                }
            } else if (10 == sortType) {// 卸车点所属工厂
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationDownFactoryName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationDownFactoryName).reversed()).collect(Collectors.toList());
                }
            } else if (11 == sortType) {// 卸车点所属车间
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationDownWorkshopName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsListParam::getLocationDownWorkshopName).reversed()).collect(Collectors.toList());
                }
            }
        }
        return records;
    }


    @PostMapping(value = "/day/getExport")
    @ApiOperation("导出磅单日报表excel/pdf")
    public Result<Object> dayExport(@RequestBody ReportsListParam param) {
        param.setSize(-1);
        Result<ZPage<ReportsListParam>> result = day(param);
        ZPage<ReportsListParam> zPage = result.getData();

        LinkedHashSet<String> headerFields = param.getHeaderFields();
        if (CollUtil.isEmpty(headerFields)) return err("导出表头不能为空");
        List<ReportsListParam> records = zPage.getRecords();
        if (CollUtil.isEmpty(records)) return err("导出数据不能为空");

        // 排序
        records = daySort(records, param.getSortType(), param.getOrderType());

        Integer flag = param.getFlag();
        // 设置总计
        setTotal(records);
        if (flag == 1) {
            excelUtils.downLoadFromWeb(response, "内部倒运日报表", headerFields, records, "模板", ReportsListParam.class);
        } else if (flag == 2) {
            pdfService.getPdf(response, "内部倒运日报表", headerFields, records, "内部倒运日报表");
        }
        return Result.ok("导出成功");
    }

    /**
     * 计算设置总计
     * @param records
     */
    private void setTotal(List<ReportsListParam> records) {
        int number;
        ReportsListParam report = new ReportsListParam();
        report.setIndex("总计");
        report.setVehNumberCount(0);
        report.setTareCount(0.0);
        report.setGrossCount(0.0);
        report.setNetCount(0.0);
        BigDecimal vehNumberCountTotal;
        BigDecimal tareCountTotal;
        BigDecimal grossCountTotal;
        BigDecimal netCountTotal;
        for (int i = 0; i < records.size(); i++) {
            ReportsListParam reportsListParam = records.get(i);
            Integer vehNumberCount = reportsListParam.getVehNumberCount();
            BigDecimal vehNumberCountTotalDecimal = vehNumberCount != null ? BigDecimal.valueOf(vehNumberCount) : new BigDecimal(0);
            vehNumberCountTotal = BigDecimal.valueOf(report.getVehNumberCount()).add(vehNumberCountTotalDecimal);
            report.setVehNumberCount(vehNumberCountTotal.intValue());

            Double tareCount = reportsListParam.getTareCount();
            BigDecimal tareCountTotalDecimal = tareCount != null ? BigDecimal.valueOf(tareCount) : new BigDecimal(0);
            tareCountTotal = BigDecimal.valueOf(report.getTareCount()).add(tareCountTotalDecimal);
            report.setTareCount(tareCountTotal.doubleValue());

            Double grossCount = reportsListParam.getGrossCount();
            BigDecimal grossCountDecimal = grossCount != null ? BigDecimal.valueOf(grossCount) : new BigDecimal(0);
            grossCountTotal = BigDecimal.valueOf(report.getGrossCount()).add(grossCountDecimal);
            report.setGrossCount(grossCountTotal.doubleValue());

            Double netCount = reportsListParam.getNetCount();
            BigDecimal netCountDecimal = netCount != null ? BigDecimal.valueOf(netCount) : new BigDecimal(0);
            netCountTotal = BigDecimal.valueOf(report.getNetCount()).add(netCountDecimal);
            report.setNetCount(netCountTotal.doubleValue());

            number = i + 1;
            reportsListParam.setIndex(number + "");
        }
        records.add(report);
    }

    /**
     * 明细报表排序
     * @param records
     * @param sortType
     * @param orderType
     * @return
     */
    private List<ReportsDetailParam> detailSort(List<ReportsDetailParam> records, Integer sortType, Integer orderType) {
        if (sortType != null && orderType != null) {
            if (1 == sortType) {// 派车单号
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getOrderNo)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getOrderNo).reversed()).collect(Collectors.toList());
                }
            } else if (4 == sortType) {// 车牌号码
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getVehNumber)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getVehNumber).reversed()).collect(Collectors.toList());
                }
            } else if (5 == sortType) {// 物料名称
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getMaterialName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getMaterialName).reversed()).collect(Collectors.toList());
                }
            } else if (6 == sortType) {// 毛重
                if (1 == orderType) {
                    records.sort((a,b)->a.getGrossCount().compareTo(b.getGrossCount()));
                } else {
                    records.sort((b,a)->a.getGrossCount().compareTo(b.getGrossCount()));
                }
            } else if (7 == sortType) {// 皮重
                if (1 == orderType) {
                    records.sort((a,b)->a.getTareCount().compareTo(b.getTareCount()));
                } else {
                    records.sort((b,a)->a.getTareCount().compareTo(b.getTareCount()));
                }
            } else if (8 == sortType) {// 净重
                if (1 == orderType) {
                    records.sort((a,b)->a.getNetCount().compareTo(b.getNetCount()));
                } else {
                    records.sort((b,a)->a.getNetCount().compareTo(b.getNetCount()));
                }
            } else if (9 == sortType) {// 装车点
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationUpName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationUpName).reversed()).collect(Collectors.toList());
                }
            } else if (10 == sortType) {// 卸车点
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationDownName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationDownName).reversed()).collect(Collectors.toList());
                }
            } else if (11 == sortType) {// 地磅单号
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getNumber)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getNumber).reversed()).collect(Collectors.toList());
                }
            } else if (12 == sortType) {// 装车点所属工厂
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationUpFactoryName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationUpFactoryName).reversed()).collect(Collectors.toList());
                }
            } else if (13 == sortType) {// 装车点所属车间
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationUpWorkshopName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationUpWorkshopName).reversed()).collect(Collectors.toList());
                }
            } else if (14 == sortType) {// 卸车点所属工厂
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationDownFactoryName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationDownFactoryName).reversed()).collect(Collectors.toList());
                }
            } else if (15 == sortType) {// 卸车点所属车间
                if (1 == orderType) {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationDownWorkshopName)).collect(Collectors.toList());
                } else {
                    records = records.stream().sorted(Comparator.comparing(ReportsDetailParam::getLocationDownWorkshopName).reversed()).collect(Collectors.toList());
                }
            }
        }
        return records;
    }

    @ApiOperation("内部倒运明细报表")
    @PostMapping(value = "/detail")
    public Result<ZPage<ReportsDetailParam>> detail(@RequestBody ReportsDetailParam param) {
        IPage iPage = new Page(param.getCurrent(), param.getSize());
        if (param.getSize() == -1) {
            iPage.setSize(Constant.maxSize);
        }
        if (param.getType() == null || param.getType() == 0) {
            param.setType(1);
        }
        IPage<ReportsDetailParam> aPage = taskService.reportDetail(iPage, param);
        ZPage<ReportsDetailParam> zPage = copyPage(aPage, ReportsDetailParam::new);
        List<ReportsDetailParam> records = zPage.getRecords();

        // 排序
        records = detailSort(records, param.getSortType(), param.getOrderType());

        // 处理负值
        if (CollUtil.isNotEmpty(records)) {
            for (ReportsDetailParam record : records) {
                Double netCount = record.getNetCount();
                netCount = netCount != null && netCount > 0 ? netCount : null;
                record.setNetCount(netCount);
            }
        }
        zPage.setRecords(records);
        return Result.ok(zPage);
    }

    @PostMapping(value = "/detail/getExport")
    @ApiOperation("导出内部倒运明细报表excel/pdf")
    public Result<Object> detailExport(@RequestBody ReportsDetailParam param) {
        param.setSize(-1);
        Result<ZPage<ReportsDetailParam>> result = detail(param);
        ZPage<ReportsDetailParam> zPage = result.getData();

        LinkedHashSet<String> headerFields = param.getHeaderFields();
        if (CollUtil.isEmpty(headerFields)) return err("导出表头不能为空");
        List<ReportsDetailParam> records = zPage.getRecords();
        if (CollUtil.isEmpty(records)) return err("导出数据不能为空");

        // 排序
        records = detailSort(records, param.getSortType(), param.getOrderType());

        // 计算总计
        ReportsDetailParam report = new ReportsDetailParam();
        report.setIndex("总计");
        report.setVehNumberCount(0);
        report.setTareCount(0.0);
        report.setGrossCount(0.0);
        report.setNetCount(0.0);
        BigDecimal vehNumberCountTotal;
        BigDecimal tareCountTotal;
        BigDecimal grossCountTotal;
        BigDecimal netCountTotal;
        int number;
        for (int i = 0; i < records.size(); i++) {
            ReportsDetailParam detail = records.get(i);
            Integer vehNumberCount = detail.getVehNumberCount();
            BigDecimal vehNumberCountTotalDecimal = vehNumberCount != null ? BigDecimal.valueOf(vehNumberCount) : new BigDecimal(0);
            vehNumberCountTotal = BigDecimal.valueOf(report.getVehNumberCount()).add(vehNumberCountTotalDecimal);
            report.setVehNumberCount(vehNumberCountTotal.intValue());

            Double tareCount = detail.getTareCount();
            BigDecimal tareCountTotalDecimal = tareCount != null ? BigDecimal.valueOf(tareCount) : new BigDecimal(0);
            tareCountTotal = BigDecimal.valueOf(report.getTareCount()).add(tareCountTotalDecimal);
            report.setTareCount(tareCountTotal.doubleValue());

            Double grossCount = detail.getGrossCount();
            BigDecimal grossCountDecimal = grossCount != null ? BigDecimal.valueOf(grossCount) : new BigDecimal(0);
            grossCountTotal = BigDecimal.valueOf(report.getGrossCount()).add(grossCountDecimal);
            report.setGrossCount(grossCountTotal.doubleValue());

            Double netCount = detail.getNetCount();
            BigDecimal netCountDecimal = netCount != null ? BigDecimal.valueOf(netCount) : new BigDecimal(0);
            netCountTotal = BigDecimal.valueOf(report.getNetCount()).add(netCountDecimal);
            report.setNetCount(netCountTotal.doubleValue());

            number = i + 1;
            detail.setIndex(number + "");
        }
        records.add(report);

        Integer flag = param.getFlag();
        if (flag == 1) {
            excelUtils.downLoadFromWeb(response, "内部倒运磅单明细表", headerFields, records, "模板", ReportsDetailParam.class);
        } else if (flag == 2) {
            pdfService.getPdf(response, "内部倒运磅单明细表", headerFields, records, "内部倒运磅单明细表");
        }
        return Result.ok("导出成功");
    }

    @ApiOperation("各车间统计日报表")
    @PostMapping(value = "/workshop-day")
    public Result<ZPage<ReportsListParam>> workshopDay(@RequestBody ReportsListParam param) {
        IPage iPage = new Page(param.getCurrent(), param.getSize());
        if (param.getSize() == -1) {
            iPage.setSize(Constant.maxSize);
        }
        IPage<ReportsListParam> aPage = taskService.reportList(iPage, param);
        ZPage<ReportsListParam> zPage = copyPage(aPage, ReportsListParam::new);
        List<ReportsListParam> records = zPage.getRecords();
        // 排序
        zPage.setRecords(daySort(records, param.getSortType(), param.getSortType()));
        return Result.ok(zPage);
    }


    @PostMapping(value = "/workshopDay/getExport")
    @ApiOperation("导出各车间统计日报表excel/pdf")
    public Result<Object> workshopDayExport(@RequestBody ReportsListParam param) {
        param.setSize(-1);
        Result<ZPage<ReportsListParam>> result = workshopDay(param);
        ZPage<ReportsListParam> zPage = result.getData();

        LinkedHashSet<String> headerFields = param.getHeaderFields();
        if (CollUtil.isEmpty(headerFields)) return err("导出表头不能为空");
        List<ReportsListParam> records = zPage.getRecords();
        if (CollUtil.isEmpty(records)) return err("导出数据不能为空");

        // 排序
        records = daySort(records, param.getSortType(), param.getOrderType());
        // 设置总计
        setTotal(records);
        Integer flag = param.getFlag();
        if (flag == 1) {
            excelUtils.downLoadFromWeb(response, "内部倒运各车间统计日报表", headerFields, records, "模板", ReportsListParam.class);
        } else if (flag == 2) {
            pdfService.getPdf(response, "内部倒运各车间统计日报表", headerFields, records, "内部倒运各车间统计日报表");
        }
        return Result.ok("导出成功");
    }
}
